﻿// virtualdevice.cpp
#include "virtualdevice.h"
#include <QTcpSocket>
#include <QHostAddress>
#include <QThread>
#include <QDateTime>
#include <QDebug>

VirtualDevice::VirtualDevice(const QString &ip, quint16 port, QObject *parent)
    : QObject(parent)
    , m_ip(ip)
    , m_port(port)
    , m_server(new QTcpServer(this))
    , m_isRunning(false)
{
    connect(m_server, &QTcpServer::newConnection, this, &VirtualDevice::onNewConnection);
}

VirtualDevice::~VirtualDevice()
{
    stop();
}

bool VirtualDevice::start()
{
    QMutexLocker locker(&m_mutex);
    if (m_isRunning) {
        log("Server is already running.");
        return false;
    }

    QHostAddress address(m_ip);
    if (address.isNull() && m_ip != "localhost") {
        log(QString("Invalid IP address: %1").arg(m_ip));
        return false;
    }
    if (m_ip == "localhost") {
        address = QHostAddress::LocalHost;
    }

    if (!m_server->listen(address, m_port)) {
        log(QString("Failed to start server: %1").arg(m_server->errorString()));
        return false;
    }

    m_isRunning = true;
    log(QString("Server listening on %1:%2").arg(m_ip).arg(m_port));
    return true;
}

void VirtualDevice::stop()
{
    QMutexLocker locker(&m_mutex);
    if (!m_isRunning) {
        return;
    }

    log("Stopping server...");
    m_isRunning = false;

    for (QTcpSocket *socket : m_clientBuffers.keys()) {
        socket->disconnectFromHost();
        if (socket->state() != QAbstractSocket::UnconnectedState) {
            socket->waitForDisconnected(1000);
        }
        socket->deleteLater();
    }
    m_clientBuffers.clear();

    if (m_server->isListening()) {
        m_server->close();
    }
    log("Server stopped.");
}

bool VirtualDevice::isRunning() const
{
    QMutexLocker locker(&m_responseMutex);
    return m_isRunning;
}

void VirtualDevice::setResponse(const QString &command, const QString &response)
{
    QMutexLocker locker(&m_responseMutex);
    m_customResponses[command] = response;
}

QString VirtualDevice::getResponse(const QString &command) const
{
    QMutexLocker locker(&m_responseMutex);
    auto it = m_customResponses.find(command);
    if (it != m_customResponses.end()) {
        return it.value();
    }
    return QString(); // 返回空字符串表示没有自定义响应
}

void VirtualDevice::onNewConnection()
{
    while (m_server->hasPendingConnections()) {
        QTcpSocket *clientSocket = m_server->nextPendingConnection();
        if (clientSocket) {
            QString clientInfo = QString("%1:%2").arg(clientSocket->peerAddress().toString()).arg(clientSocket->peerPort());
            log(QString("New connection from %1").arg(clientInfo));
            connect(clientSocket, &QTcpSocket::readyRead, this, &VirtualDevice::onReadyRead);
            connect(clientSocket, &QTcpSocket::disconnected, this, &VirtualDevice::onClientDisconnected);
            m_clientBuffers.insert(clientSocket, QString());
        }
    }
}

void VirtualDevice::onReadyRead()
{
    QTcpSocket *clientSocket = qobject_cast<QTcpSocket *>(sender());
    if (!clientSocket)
        return;

    // 将新数据追加到该客户端的缓冲区
    QByteArray data = clientSocket->readAll();
    QString &buffer = m_clientBuffers[clientSocket];
    buffer.append(QString::fromUtf8(data));

    // --- 修改部分：兼容 Qt 5.12.6 ---
    // Qt 5.12.6 使用 QString::SkipEmptyParts
    QStringList lines = buffer.split('\n', QString::SkipEmptyParts);
    // 检查原始缓冲区是否以 \n 结尾，以决定是否保留最后一个（可能不完整的）部分
    bool endsWithNewline = buffer.endsWith('\n');
    buffer.clear();
    if (!endsWithNewline && !lines.isEmpty()) {
        // 如果不以 \n 结尾，则最后一个元素是不完整的，需要保留在缓冲区中
        buffer = lines.takeLast();
    }
    // --- 修改结束 ---

    QString clientInfo = QString("%1:%2").arg(clientSocket->peerAddress().toString()).arg(clientSocket->peerPort());
    for (const QString &line : lines) {
        QString command = line.trimmed();
        if (!command.isEmpty()) {
            log(QString("Received from %1: '%2'").arg(clientInfo, command));

            QString response = generateResponse(command);
            QString responseWithNewline = response + "\n";
            qDebug() << clientInfo << response;
            QThread::msleep(200);
            qint64 bytesWritten = clientSocket->write(responseWithNewline.toUtf8());
            if (bytesWritten == -1) {
                log(QString("Failed to write response to %1").arg(clientInfo));
            } else {
                log(QString("Sent to %1: '%2'").arg(clientInfo, response));
            }
            clientSocket->flush();
        }
    }
}

void VirtualDevice::onClientDisconnected()
{
    QTcpSocket *clientSocket = qobject_cast<QTcpSocket *>(sender());
    if (clientSocket) {
        QString clientInfo = QString("%1:%2").arg(clientSocket->peerAddress().toString()).arg(clientSocket->peerPort());
        log(QString("Client disconnected: %1").arg(clientInfo));
        m_clientBuffers.remove(clientSocket);
        clientSocket->deleteLater();
    }
}

QString VirtualDevice::generateResponse(const QString &command)
{
    // 1. 检查是否有自定义响应
    {
        QMutexLocker locker(&m_responseMutex);
        auto it = m_customResponses.find(command);
        if (it != m_customResponses.end()) {
            return it.value();
        }
    } // 锁在此处释放

    // 2. 默认响应逻辑 (可以根据需要扩展)
    if (command == "connect") {
        return "OK";
    }
    if (command.startsWith("setFrequency")) {
        return "OK";
    }
    if (command.startsWith("setAmplitude")) {
        return "OK";
    }
    if (command == "setOutput true" || command == "setOutput false") {
        return "OK";
    }

    // 3. 对于未识别的命令，返回一个通用的成功响应
    log(QString("Unknown command '%1', sending default 'OK'").arg(command));

    return "OK";
}

void VirtualDevice::log(const QString &msg)
{
    QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
    QString fullMessage = QString("[%1] [%2:%3] %4").arg(timestamp).arg(m_ip).arg(m_port).arg(msg);
    emit logMessage(fullMessage);
}
